package com.lft.doublelinkedlist;

public class DoubleLinkedListUtil {
	/**
	 * 【添加】
	 * 添加到默认链表的最后
	 * @param originalHead 原始链表头节点
	 * @param newHead      新链表节点
	 * @return 返回添加之后的链表。
	 */
	public static HeroNode add(HeroNode originalHead, HeroNode newHead) {
		if (originalHead == null && newHead == null) {
			return null;
		}
		if (originalHead == null) {
			return newHead;
		}
		if (newHead == null) {
			return originalHead;
		}
		HeroNode temp = originalHead;
		// 遍历链表。找到最后一个。
		while (temp.next != null) {
			temp = temp.next;
		}
		// 将新链表添加到原链表末端。
		temp.next = newHead;
		// 形成一个双向链表。
		newHead.pre = temp;
		return originalHead;
	}
	
	/**
	 * 【按序添加】
	 * @param originalHead 原链表
	 * @param newHead      新节点
	 * @return 返回添加之后的链表
	 */
	public static HeroNode addByOrder(HeroNode originalHead, HeroNode newHead) {
		if (originalHead == null && newHead == null) {
			return null;
		}
		if (originalHead == null) {
			return newHead;
		}
		if (newHead == null) {
			return originalHead;
		}
		// 新建一个头节点，指向原链表的头部。
		HeroNode pStart = new HeroNode(0, "", "");
		pStart.next = originalHead;
		
		// 定义一个临时指针。
		HeroNode temp = pStart;
		boolean flag = false;
		
		while (temp.next != null) {
			// 遍历到的当前节点的下一个节点的排名大于新节点的排名。当前节点和下一个节点之间的位置就是要插入的位置。
			if (temp.next.no > newHead.no) {
				break;
			} else if (temp.next.no == newHead.no) {
				// 要插入的节点编号已经存在。
				flag = true;
				break;
			} else {
				// 后移遍历
				temp = temp.next;
			}
		}
		if (flag) {
			System.out.printf("准备添加的英雄的编号 %d 已经存在，不能加入。\n", newHead.no);
		} else if (temp.next != null) {
			temp.next.pre = newHead;
			newHead.pre = temp;
			newHead.next = temp.next;
			temp.next = newHead;
		} else {
			temp.next = newHead;
			newHead.pre = temp;
		}
		originalHead = pStart.next;
		return originalHead;
	}
	
	/**
	 * 【修改节点】
	 * @param originalHead 原始链表头节点
	 * @param newHead      带新内容的节点
	 * @return 修改后的链表
	 */
	public static HeroNode update(HeroNode originalHead, HeroNode newHead) {
		if (originalHead == null || newHead == null) {
			return originalHead;
		}
		HeroNode temp = originalHead;
		boolean flag = false;
		while (true) {
			if (temp == null) {
				break;
			}
			if (temp.no == newHead.no) {
				flag = true;
				break;
			}
			temp = temp.next;
		}
		if (flag) {
			temp.name = newHead.name;
			temp.nickName = newHead.nickName;
		} else {
			System.out.println("未能找到编号 %d 的节点，无法修改。\n" + newHead.no);
		}
		return originalHead;
	}
	
	/**
	 * 【删除节点】
	 * @param originalHead 原始链表
	 * @param no           要删除节点的no号
	 * @return 返回删除后的链表
	 * 1. 对于双向链表，我们可以直接找到要删除的这个节点。
	 * 2. 找到之后，自我删除即可。
	 */
	public static HeroNode delete(HeroNode originalHead, int no) {
		// 判断当前链表是否为空。
		if (originalHead == null) {
			System.out.println("链表为空不能删除。");
			return null;
		}
		// 辅助节点(变量/指针)
		HeroNode temp = originalHead;
		// 标志是否找到待删除的节点。
		boolean flag = false;
		while (true) {
			// 遍历到链表的最后。
			if (temp == null) {
				break;
			}
			// 找到待删除的节点。
			if (temp.no == no) {
				flag = true;
				break;
			}
			temp = temp.next;
		}
		if (flag) {
			temp.pre.next = temp.next;
			if (temp.next != null) {
				temp.next.pre = temp.pre;
			}
		} else {
			System.out.println("未能找到编号 %d 的节点，无法删除。\n" + no);
		}
		return originalHead;
	}
	
	/**
	 * 遍历双向链表
	 * @param head 需要遍历的链表。
	 */
	public static void list(HeroNode head) {
		if (head == null) {
			System.out.println("双向链表为空");
			return;
		}
		HeroNode temp = head;
		while (temp != null) {
			System.out.println(temp);
			temp = temp.next;
		}
	}
}
